Fix mapping of shared ring pages into backend drivers.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 21 Sep 2005 16:36:46 +0000 (16:36 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 21 Sep 2005 16:36:46 +0000 (16:36 +0000)
This should fix observed problems when creating a domain,
causing Xen to print "Could not find PTE entry for
address ...".

Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/Makefile
linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
linux-2.6-xen-sparse/drivers/xen/blktap/interface.c
linux-2.6-xen-sparse/drivers/xen/netback/interface.c
linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c
linux-2.6-xen-sparse/drivers/xen/usbback/interface.c
linux-2.6-xen-sparse/drivers/xen/util.c [new file with mode: 0644]
linux-2.6-xen-sparse/include/asm-xen/driver_util.h [new file with mode: 0644]

index 83f63cd7bbebd0bc5c3cc912fc06f9a9f1abf0f3..d7a3e80ccd1bafeb165fb86aa0abf31f42068f2e 100644 (file)
@@ -1,4 +1,5 @@
 
+obj-y  += util.o
 
 obj-y  += console/
 obj-y  += evtchn/
index 79b37abc09a679e77b082f1d352902b23d394546..a31fc0964bb0bbc4cd4627f8a6e3aa4927d0285b 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "common.h"
 #include <asm-xen/evtchn.h>
+#include <asm-xen/driver_util.h>
 
 static kmem_cache_t *blkif_cachep;
 
@@ -69,12 +70,12 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
 
     BUG_ON(blkif->remote_evtchn);
 
-    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+    if ( (vma = prepare_vm_area(PAGE_SIZE)) == NULL )
        return -ENOMEM;
 
     err = map_frontend_page(blkif, (unsigned long)vma->addr, shared_page);
     if (err) {
-        vfree(vma->addr);
+        vunmap(vma->addr);
        return err;
     }
 
@@ -85,7 +86,7 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
     err = HYPERVISOR_event_channel_op(&op);
     if (err) {
        unmap_frontend_page(blkif);
-       vfree(vma->addr);
+       vunmap(vma->addr);
        return err;
     }
 
@@ -123,7 +124,7 @@ static void free_blkif(void *arg)
 
     if (blkif->blk_ring.sring) {
        unmap_frontend_page(blkif);
-       vfree(blkif->blk_ring.sring);
+       vunmap(blkif->blk_ring.sring);
        blkif->blk_ring.sring = NULL;
     }
 
index 6f9aae9ccce6a79b90f1e6efcbc89fbdecb79d2a..28814b5aef175ede3dfdaf78f4a4c3e97d4ab8ce 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "common.h"
 #include <asm-xen/evtchn.h>
+#include <asm-xen/driver_util.h>
 
 static kmem_cache_t *blkif_cachep;
 
@@ -69,12 +70,12 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
 
     BUG_ON(blkif->remote_evtchn);
 
-    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+    if ( (vma = prepare_vm_area(PAGE_SIZE)) == NULL )
        return -ENOMEM;
 
     err = map_frontend_page(blkif, (unsigned long)vma->addr, shared_page);
     if (err) {
-        vfree(vma->addr);
+        vunmap(vma->addr);
        return err;
     }
 
@@ -85,7 +86,7 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
     err = HYPERVISOR_event_channel_op(&op);
     if (err) {
        unmap_frontend_page(blkif);
-       vfree(vma->addr);
+       vunmap(vma->addr);
        return err;
     }
 
@@ -121,7 +122,7 @@ static void free_blkif(void *arg)
 
     if (blkif->blk_ring.sring) {
        unmap_frontend_page(blkif);
-       vfree(blkif->blk_ring.sring);
+       vunmap(blkif->blk_ring.sring);
        blkif->blk_ring.sring = NULL;
     }
 
index 311f426d0b800e797c858ca54e7b96c3f8bfc85f..1f62e35438d01abd7fb14e0dda574c1d6b8004dd 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "common.h"
 #include <linux/rtnetlink.h>
+#include <asm-xen/driver_util.h>
 
 static void __netif_up(netif_t *netif)
 {
@@ -198,14 +199,14 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref,
        evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
        int err;
 
-       vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP);
+       vma = prepare_vm_area(2*PAGE_SIZE);
        if (vma == NULL)
                return -ENOMEM;
 
        err = map_frontend_pages(
                netif, (unsigned long)vma->addr, tx_ring_ref, rx_ring_ref);
        if (err) {
-               vfree(vma->addr);
+               vunmap(vma->addr);
                return err;
        }
 
@@ -216,7 +217,7 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref,
        err = HYPERVISOR_event_channel_op(&op);
        if (err) {
                unmap_frontend_pages(netif);
-               vfree(vma->addr);
+               vunmap(vma->addr);
                return err;
        }
 
@@ -261,7 +262,7 @@ static void free_netif_callback(void *arg)
 
        if (netif->tx) {
                unmap_frontend_pages(netif);
-               vfree(netif->tx); /* Frees netif->rx as well. */
+               vunmap(netif->tx); /* Frees netif->rx as well. */
        }
 
        free_netdev(netif->dev);
index 3c585e6bcd99abc4bc890c8969efc541aca6a330..d05f91d06628a81c0ab2064c62331f0a0a2ab2ab 100644 (file)
@@ -1,4 +1,4 @@
- /******************************************************************************
+ /*****************************************************************************
  * drivers/xen/tpmback/interface.c
  *
  * Vritual TPM interface management.
@@ -13,6 +13,7 @@
 
 #include "common.h"
 #include <asm-xen/balloon.h>
+#include <asm-xen/driver_util.h>
 
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
 
@@ -122,12 +123,12 @@ tpmif_map(tpmif_t * tpmif, unsigned long shared_page, unsigned int evtchn)
 
        BUG_ON(tpmif->remote_evtchn);
 
-       if ((vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL)
+       if ((vma = prepare_vm_area(PAGE_SIZE)) == NULL)
                return -ENOMEM;
 
        err = map_frontend_page(tpmif, VMALLOC_VMADDR(vma->addr), shared_page);
        if (err) {
-               vfree(vma->addr);
+               vunmap(vma->addr);
                return err;
        }
 
@@ -138,7 +139,7 @@ tpmif_map(tpmif_t * tpmif, unsigned long shared_page, unsigned int evtchn)
        err = HYPERVISOR_event_channel_op(&op);
        if (err) {
                unmap_frontend_page(tpmif);
-               vfree(vma->addr);
+               vunmap(vma->addr);
                return err;
        }
 
@@ -174,7 +175,7 @@ __tpmif_disconnect_complete(void *arg)
 
        if (tpmif->tx) {
                unmap_frontend_page(tpmif);
-               vfree(tpmif->tx);
+               vunmap(tpmif->tx);
        }
 
        free_tpmif(tpmif);
index ab44ed304048fe0fad816f90425a1b304b98ef8f..fe091aad360f3ab039081adaa3a266f8651b1abe 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "common.h"
+#include <asm-xen/driver_util.h>
 
 #define USBIF_HASHSZ 1024
 #define USBIF_HASH(_d) (((int)(_d))&(USBIF_HASHSZ-1))
@@ -33,7 +34,7 @@ static void __usbif_disconnect_complete(void *arg)
      * may be outstanding requests at the device whose asynchronous responses
      * must still be notified to the remote driver.
      */
-    vfree(usbif->usb_ring.sring);
+    vunmap(usbif->usb_ring.sring);
 
     /* Construct the deferred response message. */
     cmsg.type         = CMSG_USBIF_BE;
@@ -154,7 +155,7 @@ void usbif_connect(usbif_be_connect_t *connect)
         return;
     }
 
-    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
+    if ( (vma = prepare_vm_area(PAGE_SIZE)) == NULL )
     {
         connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
         return;
@@ -172,14 +173,14 @@ void usbif_connect(usbif_be_connect_t *connect)
             connect->status = USBIF_BE_STATUS_MAPPING_ERROR;
         else
             connect->status = USBIF_BE_STATUS_ERROR;
-        vfree(vma->addr);
+        vunmap(vma->addr);
         return;
     }
 
     if ( up->status != DISCONNECTED )
     {
         connect->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
-        vfree(vma->addr);
+        vunmap(vma->addr);
         return;
     }
 
diff --git a/linux-2.6-xen-sparse/drivers/xen/util.c b/linux-2.6-xen-sparse/drivers/xen/util.c
new file mode 100644 (file)
index 0000000..04c5984
--- /dev/null
@@ -0,0 +1,46 @@
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
+
+static int touch_fn(
+       pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
+{
+       char c;
+       BUG_ON(!__get_user(c, (char *)addr));
+       return 0;
+}
+
+struct vm_struct *prepare_vm_area(unsigned long size)
+{
+       struct vm_struct *area;
+
+       area = get_vm_area(size, VM_IOREMAP);
+       if (area == NULL)
+               return NULL;
+
+       /*
+         * This ensures that page tables are constructed for this region
+         * of kernel virtual address space. Furthermore, by touching each
+         * memory page (in touch_fn()) we ensure that the page tables are
+         * mapped into the current mm as well as init_mm.
+         */
+       if (generic_page_range(&init_mm, (unsigned long)area->addr,
+                              area->size, touch_fn, NULL)) {
+               vunmap(area->addr);
+               return NULL;
+       }
+
+       return area;
+}
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff --git a/linux-2.6-xen-sparse/include/asm-xen/driver_util.h b/linux-2.6-xen-sparse/include/asm-xen/driver_util.h
new file mode 100644 (file)
index 0000000..142b228
--- /dev/null
@@ -0,0 +1,10 @@
+
+#ifndef __ASM_XEN_DRIVER_UTIL_H__
+#define __ASM_XEN_DRIVER_UTIL_H__
+
+#include <linux/config.h>
+#include <linux/vmalloc.h>
+
+extern struct vm_struct *prepare_vm_area(unsigned long size);
+
+#endif /* __ASM_XEN_DRIVER_UTIL_H__ */